<?php

namespace App\Common\SDK\Domain;

class ShanDe extends Base
{
    public function __construct()
    {
        parent::__construct();
    }

    private function sign($params)
    {
        $params = json_encode($params);
        $resource = openssl_pkey_get_private(self::loadPk12Cert());
        $result = openssl_sign($params, $sign, $resource);
        openssl_free_key($resource);
        if (!$result) {
            abort(400, '签名错误: 加签失败');
        }

        return base64_encode($sign);
    }

    public static function signVerify($params = [])
    {
        $resource = openssl_pkey_get_public(self::loadX509Cert());
        $result = openssl_verify($params['data'], base64_decode($params['sign']), $resource);
        openssl_free_key($resource);

        if ($result) {
            abort(400, '验签失败: 签名错误');
        }
    }

    protected function assembleParams($params)
    {
        return [
            'charset' => 'utf-8',
            'signType' => '01',
            'data' => json_encode($params),
            'sign' => $this->sign($params)
        ];
    }

    protected function requestAfter($response)
    {
        parse_str(urldecode($response), $response);
        self::signVerify($response);

        $response = json_decode($response['data'], true);
        \Log::info('经过解析后的杉德返回数据: ' . json_encode($response));

        if ($response['head']['respCode'] !== '000000') {
            abort(400, '支付渠道发生错误: ' . $response['head']['respMsg']);
        }

        return $response['body'];
    }

    /**
     * 统一下单
     * @param array $params
     * @return mixed
     * @throws \Exception
     */
    public function gateWayOrderPay($params = [])
    {
        return $this->request(Base::METHOD_POST, 'gateway/api/order/pay', $params, Base::FORMATTED_DATA_TYPE_URLENCODE, false);
    }

    /**
     * 主动查询订单状态
     * @param array $params
     * @return mixed
     * @throws \Exception
     */
    public function getPaymentOrderDetail($params = [])
    {
        return $this->request(Base::METHOD_POST, 'gateway/api/order/query', $params, Base::FORMATTED_DATA_TYPE_URLENCODE, false);
    }

    /**
     * 获取私钥
     * @return mixed
     */
    public static function loadPk12Cert()
    {
        $file = file_get_contents(resource_path(sprintf('shande/%s.pfx', env('SHAN_DE_MID'))));
        if (!$file) {
            abort(400, '验签错误: 获取私钥失败');
        }
        if (!openssl_pkcs12_read($file, $cert, env('SHAN_DE_SECRET'))) {
            abort(400, '验签错误: 获取私钥失败');
        }

        return $cert['pkey'];
    }

    /**
     * 获取公钥
     * @return false|mixed
     */
    public static function loadX509Cert()
    {
        $file = file_get_contents(resource_path(sprintf('shande/%s.cer', env('SHAN_DE_MID'))));
        $cert = chunk_split(base64_encode($file), 64, "\n");
        $cert = "-----BEGIN CERTIFICATE-----\n" . $cert . "-----END CERTIFICATE-----\n";
        $res = openssl_pkey_get_public($cert);
        $detail = openssl_pkey_get_details($res);
        openssl_free_key($res);
        if (!$detail) {
            abort(400, '验签错误: 获取公钥失败');
        }

        return $detail['key'];
    }
}
